package com.example.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class RabbitMQConsumerTest {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();

        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("123456");
        connectionFactory.setVirtualHost("/");

        Connection connection = connectionFactory.newConnection("李四");
        Channel channel = connection.createChannel();
        // 声明一个队列
        // queueDeclare()方法参数说明：
        // queue – 队列的名称
        // durable（持久） - 如果我们声明一个持久队列，则为真（该队列将在服务器重启后继续存在）
        // exclusive（独占） – 如果我们声明独占队列（仅限于此连接），则为 true
        // autoDelete – 如果我们声明一个自动删除队列，则为 true（服务器将在不再使用时将其删除）
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        // 参数：
        // consumerTag – 与消费者关联的消费者标签
        // message – 传递的消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {

            String messageText = new String(message.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + messageText + "'");
            // 手动进行ACK
            /*
             *  void basicAck(long deliveryTag, boolean multiple) throws IOException;
             *  - deliveryTag: 用来标识消息的id
             *  - multiple: 是否批量。true:将一次性ack所有小于deliveryTag的消息。
             */
            Envelope envelope = message.getEnvelope();
            channel.basicAck(envelope.getDeliveryTag(), false);
        };

        /**
         * basicConsume()方法参数明细：
         * 1、queue 队列名称
         * 2、autoAck 自动回复，当消费者接收到消息后要告诉mq消息已接收，如果将此参数设置为tru表示会自动回复mq，如果设置为false要通过编程实现回复
         * 3、deliverCallback，消费方法，当消费者接收到消息要执行的方法
         * 4、cancelCallback 消费者取消时的回调
         */
        // 将autoAck设置为false, 收到消息后不自动回复，改为收到调用channel.basicAck()方法进行回复
        channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> { });
    }
}
